package com.didd.core.common.utils;

import cn.hutool.core.util.NumberUtil;

import java.math.BigDecimal;
import java.math.RoundingMode;
import java.util.Objects;

/**
 * 金额工具类, 针对金额乘以10000
 *
 * @author diddd
 * @since 2019/9/18
 */
public class MoneyUtil {

    /**
     * 万分位计算
     */
    private static final BigDecimal TEN_THOUSAND_BIT = new BigDecimal(10000);
    /**
     * 黙认2位小数
     */
    private static final int DEFAULT_SCALE = 2;

    /**
     * Long去万分位转换BigDecimal
     *
     * @param amount 金额
     */
    public static BigDecimal convert(Long amount) {
        return convert(amount, DEFAULT_SCALE);
    }

    /**
     * Long去万分位转换BigDecimal
     *
     * @param amount       金额
     * @param roundingMode 保存小数 {@link BigDecimal}
     */
    public static BigDecimal convert(Long amount, int roundingMode) {
        if (Objects.isNull(amount)) {
            throw new NullPointerException();
        }

        if (amount == 0L) {
            return BigDecimal.ZERO;
        }

        BigDecimal money = BigDecimal.valueOf(amount);
        return NumberUtil.div(money, TEN_THOUSAND_BIT, roundingMode, RoundingMode.HALF_UP);
    }

    /**
     * BigDecimal乘以万分位转换Long
     *
     * @param amount       金额
     * @param roundingMode 保存小数
     */
    public static Long convert(BigDecimal amount, int roundingMode) {
        if (Objects.isNull(amount)) {
            throw new NullPointerException();
        }

        if (amount.compareTo(BigDecimal.ZERO) == 0) {
            return 0L;
        }
        amount = amount.setScale(roundingMode, RoundingMode.HALF_UP);
        return NumberUtil.mul(amount, TEN_THOUSAND_BIT).longValue();
    }

    /**
     * BigDecimal乘以万分位转换Long
     * 默认保留2位小数
     *
     * @param amount 金额
     */
    public static Long convert(BigDecimal amount) {
        return convert(amount, DEFAULT_SCALE);
    }

    /**
     * 非万分位Long转换万分位Long
     *
     * @param amount 金额
     */
    public static Long toTenThousandBit(Long amount) {
        if (Objects.isNull(amount)) {
            throw new NullPointerException();
        }
        if (amount == 0L) {
            return 0L;
        }
        BigDecimal money = new BigDecimal(amount);
        BigDecimal resultMoney = money.multiply(TEN_THOUSAND_BIT);
        return resultMoney.longValue();
    }

    /**
     * 非万分位BigDecimal转换万分位BigDecimal
     *
     * @param amount 金额
     */
    public static BigDecimal toTenThousandBit(BigDecimal amount) {
        if (Objects.isNull(amount)) {
            throw new NullPointerException();
        }

        if (amount.compareTo(BigDecimal.ZERO) == 0) {
            return BigDecimal.ZERO;
        }

        return amount.multiply(TEN_THOUSAND_BIT);
    }

    /**
     * 正常金额乘以数量后转换成万分位Long型
     *
     * @param amount 金额
     * @param number 数量
     */
    public static Long mul(Long amount, BigDecimal number) {
        BigDecimal money = MoneyUtil.convert(amount);
        BigDecimal resultMoney = money.multiply(number);
        return MoneyUtil.convert(resultMoney);
    }

    /**
     * 真实金额 单位元
     *
     * @param amount 金额
     * @return
     */
    public static BigDecimal realAmount(Number amount) {
        if (amount == null || BigDecimal.ZERO.equals(new BigDecimal(amount.toString()))) {
            return BigDecimal.ZERO;
        }
        return new BigDecimal(amount.toString()).divide(TEN_THOUSAND_BIT, DEFAULT_SCALE, RoundingMode.HALF_UP);
    }

    /**
     * 真实金额 单位元
     *
     * @param amount       金额
     * @param scale        小数位
     * @param roundingMode 进位方式
     * @return
     */
    public static BigDecimal realAmount(Number amount, Integer scale, RoundingMode roundingMode) {
        if (amount == null || BigDecimal.ZERO.equals(new BigDecimal(amount.toString()))) {
            return BigDecimal.ZERO;
        }
        return new BigDecimal(amount.toString()).divide(TEN_THOUSAND_BIT, scale, roundingMode);
    }

    /**
     * 金额扩大 10000倍
     *
     * @param amount 金额
     * @return
     */
    public static BigDecimal expandAmount(Number amount) {
        if (amount == null || BigDecimal.ZERO.equals(new BigDecimal(amount.toString()))) {
            return BigDecimal.ZERO;
        }
        return new BigDecimal(amount.toString()).multiply(TEN_THOUSAND_BIT).setScale(DEFAULT_SCALE, RoundingMode.HALF_UP);
    }

    /**
     * 金额扩大 10000倍
     *
     * @param amount       金额
     * @param scale        小数位
     * @param roundingMode 进位方式
     * @return
     */
    public static BigDecimal expandAmount(Number amount, Integer scale, RoundingMode roundingMode) {
        if (amount == null || BigDecimal.ZERO.equals(new BigDecimal(amount.toString()))) {
            return BigDecimal.ZERO;
        }
        return new BigDecimal(amount.toString()).multiply(TEN_THOUSAND_BIT).setScale(scale, roundingMode);
    }
}
